package com.smzd.framework.sso;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.ProviderNotFoundException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.savedrequest.DefaultSavedRequest;

import com.smzd.framework.security.domain.Authority;
import com.smzd.framework.sso.domain.SocialUser;
import com.smzd.framework.system.business.UserBindService;
import com.smzd.framework.system.business.UserService;
import com.smzd.framework.system.domain.Meeting;
import com.smzd.framework.system.domain.User;
import com.smzd.framework.system.domain.UserBind;

@Deprecated
public class BaseXtwlAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
    public static final int STRATEGY_SILENCE_REGISTER = 0;
    public static final int STRATEGY_CUSTOMIZE_USER = 1;
    public static final int STRATEGY_LOCAL_LOGIN = 2;

    protected String ticketParamName = "code";
    protected List<? extends OAuth2AuthenticationProcessor> processors;
    protected int strategy;

    private final static List<GrantedAuthority> authorities = Arrays.asList((GrantedAuthority) new Authority(
            "ROLE_USER"));

    @Autowired
    private UserBindService userBindService;
    @Autowired
    private UserService userService;
    private String customizeUserInfoUri;

    public BaseXtwlAuthenticationProcessingFilter() {
        this("/sso/xtwl_getticket");
    }

    public BaseXtwlAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String state = request.getParameter("state");
        if (state == null) {
            state = "xtwlcas";
        }
        String queryString = request.getQueryString();
        System.out.println("queryString=" + queryString);
        OAuth2AuthenticationProcessor chosenProcessor = null;
        for (OAuth2AuthenticationProcessor processor : processors) {
            if (processor.support(state)) {
                chosenProcessor = processor;
                break;
            }
        }
        if (chosenProcessor != null) {
            try {
                Object accessToken = chosenProcessor.getAccessToken(queryString);
                Object remoteUserInfo = chosenProcessor.getRemoteUserInfo(accessToken);
                SocialUser socialUser = chosenProcessor.convertRemoteToSocialUser(remoteUserInfo);

                UserBind userBind = userBindService.getUserBindByOpenid(socialUser.getOpenid());
                if (userBind == null) {
                    int type = chosenProcessor.getPlatform();
                    if (strategy == STRATEGY_SILENCE_REGISTER) {
                        // 自动注册本地用户
                        User localUser = silenceRegistUser(socialUser, type);
                        // 设置新用户自动登录
                        localUser.setAuthorities(authorities);
                        return new UsernamePasswordAuthenticationToken(localUser, "PASS", localUser.getAuthorities());
                    } else {
                        String base = request.getContextPath();
                        if (base.length() == 1) {
                            base = "";
                        }
                        HttpSession session = request.getSession();
                        DefaultSavedRequest saved = (DefaultSavedRequest) session
                                .getAttribute("SPRING_SECURITY_SAVED_REQUEST");
                        if (saved == null) {
                            response.sendRedirect(base + "/");
                        }

                        if (strategy == STRATEGY_CUSTOMIZE_USER) {

                            response.sendRedirect(base + customizeUserInfoUri);
                        } else if (strategy == STRATEGY_LOCAL_LOGIN) {

                        }
                    }
                    return null;
                } else {
                    // 再有本地用户的情况下，需要区分两种情况:
                    // 1.
                    // 用户已经认证登录了，此时不要因此而重新登录一遍，通常这是在绑定用户，也可能是在做其他的刷新社交信息的操作，因此要看保存的目的是什么，直接转过去即可。
                    // 2. 用户尚未认证登录，此时不要犹豫了，就是要登录
                    User localUser = userService.getItemById(userBind.getOwner().getId());
                    if (localUser != null) {
                        localUser.setAuthorities(authorities);
                        return new UsernamePasswordAuthenticationToken(localUser, "PASS", localUser.getAuthorities());
                    } else {
                        throw new AuthenticationCredentialsNotFoundException("Local User NOT Found! Expected User ID: "
                                + userBind.getOwner().getId());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new BadCredentialsException("认证过程中出现错误！", e);
            }
        }
        throw new ProviderNotFoundException("OAuth2AuthenticationProcessor not found for state: " + state);
    }

    private User silenceRegistUser(User remoteUser, int type) {
        UserBind userBind;
        User localUser = remoteUser;
        Meeting meeting = getSilenceRegistUserOwner();
        localUser.setOwner(meeting);
        localUser.setType(User.USER_TYPE_MEETING_MANAGER);
        userService.insert(localUser);
        // 自动添加本地用户和远程用户的绑定
        userBind = new UserBind();
        userBind.setOwner(localUser);
        userBind.setName(remoteUser.getName());
        userBind.setOpenid(remoteUser.getPassword());
        userBind.setType(type);
        userBindService.insert(userBind);
        return localUser;
    }

    private Meeting getSilenceRegistUserOwner() {
        Meeting meeting = new Meeting();
        meeting.setId(1);
        return meeting;
    }

    public String getTicketParamName() {
        return ticketParamName;
    }

    public void setTicketParamName(String ticketParamName) {
        this.ticketParamName = ticketParamName;
    }

    public List<? extends OAuth2AuthenticationProcessor> getProcessors() {
        return processors;
    }

    public void setProcessors(List<? extends OAuth2AuthenticationProcessor> processors) {
        this.processors = processors;
    }

    public int getStrategy() {
        return strategy;
    }

    public void setStrategy(int strategy) {
        if (strategy > STRATEGY_LOCAL_LOGIN) {
            strategy = STRATEGY_CUSTOMIZE_USER;
        }
        this.strategy = strategy;
    }

    public String getCustomizeUserInfoUri() {
        return customizeUserInfoUri;
    }

    public void setCustomizeUserInfoUri(String customizeUserInfoUri) {
        this.customizeUserInfoUri = customizeUserInfoUri;
    }

}
